/*
 * Created by JFormDesigner on Wed Dec 16 10:46:56 CET 2009
 */

package at.jku.pervasive.gui.jformdesigner;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import javax.swing.*;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import at.jku.pervasive.Application;
import at.jku.pervasive.Measurement;
import at.jku.pervasive.Position;
import at.jku.pervasive.TagPosition;
import at.jku.pervasive.TagPositionListener;
import at.jku.pervasive.recognition.GestureCharacteristics;
import at.jku.pervasive.simulator.StepwiseFileServerSimulator;

import com.jgoodies.forms.factories.FormFactory;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.ColumnSpec;
import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.forms.layout.FormSpec;
import com.jgoodies.forms.layout.RowSpec;
import com.jgoodies.forms.layout.Sizes;

/**
 * @author SHOCKIE
 */
public class ReplayMeasurementPanel extends JPanel implements TagPositionListener
{

	private Measurement loadedMeasurement;

	public ReplayMeasurementPanel()
	{
		initComponents();

		Application application = Application.getInstance();
		application.setReplayMeasurementPanel(this);

		try
		{
			fileServerSimulator = new StepwiseFileServerSimulator(application.getPort());
		} catch (IOException e2)
		{
			e2.printStackTrace();
			throw new RuntimeException(e2);
		}

		application.addTagPositionListener(this);

		loadMeasurementButton.addActionListener(new ActionListener()
		{
			@Override
			public void actionPerformed(ActionEvent e)
			{
				// open a measurement
				Application application = Application.getInstance();
				JFileChooser jFileChooser = new JFileChooser(application.getDefaultOpenMeasurementFolder());
				int chosenOption = jFileChooser.showOpenDialog(ReplayMeasurementPanel.this);
				if (chosenOption != JFileChooser.APPROVE_OPTION)
					return;

				// get the file
				File measurementFile = jFileChooser.getSelectedFile();
				try
				{
					loadedMeasurement = application.loadMeasurement(measurementFile);
				} catch (FileNotFoundException e1)
				{
					e1.printStackTrace();
					return;
				}

				int nrOfPositions = loadedMeasurement.getPositions().length;
				measurementLabel.setText(nrOfPositions + " positions");
				currentPositionSlider.setMaximum(nrOfPositions);

				application.startedTracingTag(loadedMeasurement.getLeftTagId());
				application.startedTracingTag(loadedMeasurement.getRightTagId());
				application.startedTracingTag(loadedMeasurement.getChestTagId());
				application.startedTracingTag(loadedMeasurement.getBackTagId());

				tagAssignmentPanel.setLoadedMeasurement(loadedMeasurement);
				application.tagAssignmentChanged(TagPosition.LEFT, loadedMeasurement.getLeftTagId());
				application.tagAssignmentChanged(TagPosition.RIGHT, loadedMeasurement.getRightTagId());
				application.tagAssignmentChanged(TagPosition.CHEST, loadedMeasurement.getChestTagId());
				application.tagAssignmentChanged(TagPosition.BACK, loadedMeasurement.getBackTagId());

				fileServerSimulator.setMeasurement(loadedMeasurement);
				fileServerSimulator.start();
			}
		});

		currentPositionSlider.addChangeListener(new ChangeListener()
		{
			@Override
			public void stateChanged(ChangeEvent e)
			{
				JSlider slider = (JSlider) e.getSource();
				int currentValue = slider.getValue();
				currentPositionLabel.setText("Positions: (" + currentValue + ")");

				if (!fileServerSimulator.isPlaying())
				{
					fileServerSimulator.pause();
					fileServerSimulator.step(currentValue);
				}
			}
		});

		playPauseButton.addActionListener(new ActionListener()
		{
			@Override
			public void actionPerformed(ActionEvent e)
			{
				isPlaying = !isPlaying;
				if (isPlaying)
				{
					playPauseButton.setText("pause");
					fileServerSimulator.play();
				}
				else
				{
					playPauseButton.setText("play");
					fileServerSimulator.pause();
				}
			}
		});

		loopCheckBox.addChangeListener(new ChangeListener()
		{
			@Override
			public void stateChanged(ChangeEvent e)
			{
				fileServerSimulator.setLoop(loopCheckBox.isSelected());
			}
		});

		DoubleListener dl = new DoubleListener();
		angleToleranceTextField.addKeyListener(dl);
		equalHeightToleranceTextField.addKeyListener(dl);
		lowerDifferenceTextField.addKeyListener(dl);
		zOffsetTextField.addKeyListener(dl);
		geRecoTimeTextField.addKeyListener(dl);
		geRecoTresholdTextField.addKeyListener(dl);

		angleToleranceTextField.setText("" + application.getAngleTolerance());
		equalHeightToleranceTextField.setText("" + application.getEqualToHeightTolerance());
		lowerDifferenceTextField.setText("" + application.getLowerDifferenceTolerance());
		zOffsetTextField.setText("" + application.getZOffset());
		geRecoTimeTextField.setText("" + application.getGestureRecognitionTime());
		geRecoTresholdTextField.setText("" + application.getGestureRecognitionTreshold());
	}

	class DoubleListener extends KeyAdapter
	{

		@Override
		public void keyReleased(KeyEvent e)
		{
			// is the entered value a valid double?
			JTextField textField = (JTextField) e.getSource();
			String text = textField.getText();
			try
			{
				Double.parseDouble(text);
			} catch (NumberFormatException nfe)
			{
				System.out.println("invalid");
				return;
			}

			// the value is valid, so we update the applications treshold values
			Application application = Application.getInstance();
			application.setAngleTolerance(Double.parseDouble(angleToleranceTextField.getText()));
			application.setEqualHeightTolerance(Double.parseDouble(equalHeightToleranceTextField.getText()));
			application.setLowerDifferenceTolerance(Double.parseDouble(lowerDifferenceTextField.getText()));
			application.setZOffset(Double.parseDouble(zOffsetTextField.getText()));
			application.setGestureRecognitionTime(Long.parseLong(geRecoTimeTextField.getText()));
			application.setGestureRecognitionTreshold(Double.parseDouble(geRecoTresholdTextField.getText()));
		}
	}

	private boolean isPlaying;
	private StepwiseFileServerSimulator fileServerSimulator;

	private void initComponents()
	{
		// JFormDesigner - Component initialization - DO NOT MODIFY
		// //GEN-BEGIN:initComponents
		// Generated using JFormDesigner Open Source Project license - unknown
		JLabel loadMeasurementLabel = new JLabel();
		measurementLabel = new JLabel();
		loadMeasurementButton = new JButton();
		currentPositionLabel = new JLabel();
		currentPositionSlider = new JSlider();
		playPauseButton = new JButton();
		loopCheckBox = new JCheckBox();
		JLabel angleLable = new JLabel();
		JPanel panel1 = new JPanel();
		angleIs0CheckBox = new JCheckBox();
		angleIs90CheckBox = new JCheckBox();
		angleIs180CheckBox = new JCheckBox();
		JLabel leftLabel = new JLabel();
		JPanel panel2 = new JPanel();
		leftIsLowerThanRightCheckBox = new JCheckBox();
		leftIsLowerThanRefCheckBox = new JCheckBox();
		panel6 = new JPanel();
		leftIsEqualToRightCheckBox = new JCheckBox();
		JLabel refLabel = new JLabel();
		JPanel panel3 = new JPanel();
		refIsLowerThanLeftCheckBox = new JCheckBox();
		refIsLowerThanRightCheckBox = new JCheckBox();
		JPanel panel5 = new JPanel();
		refIsEqualToLeftCheckBox = new JCheckBox();
		refIsEqualToRightCheckBox = new JCheckBox();
		JLabel rightLabel = new JLabel();
		JPanel panel4 = new JPanel();
		rightIsLowerThanLeftCheckBox = new JCheckBox();
		rightIsLowerThanRefCheckBox = new JCheckBox();
		label3 = new JLabel();
		angleToleranceTextField = new JTextField();
		label4 = new JLabel();
		equalHeightToleranceTextField = new JTextField();
		label5 = new JLabel();
		lowerDifferenceTextField = new JTextField();
		label6 = new JLabel();
		zOffsetTextField = new JTextField();
		label7 = new JLabel();
		geRecoTimeTextField = new JTextField();
		label8 = new JLabel();
		geRecoTresholdTextField = new JTextField();
		CellConstraints cc = new CellConstraints();

		// ======== this ========
		setName("this");
		setLayout(new FormLayout(new ColumnSpec[] { new ColumnSpec("right:max(default;55dlu)"),
				FormFactory.LABEL_COMPONENT_GAP_COLSPEC,
				new ColumnSpec(ColumnSpec.FILL, Sizes.DEFAULT, FormSpec.DEFAULT_GROW),
				FormFactory.LABEL_COMPONENT_GAP_COLSPEC,
				new ColumnSpec(ColumnSpec.LEFT, Sizes.DEFAULT, FormSpec.NO_GROW) }, new RowSpec[] {
				FormFactory.DEFAULT_ROWSPEC, FormFactory.LINE_GAP_ROWSPEC, FormFactory.DEFAULT_ROWSPEC,
				FormFactory.LINE_GAP_ROWSPEC, FormFactory.DEFAULT_ROWSPEC, FormFactory.LINE_GAP_ROWSPEC,
				FormFactory.DEFAULT_ROWSPEC, FormFactory.LINE_GAP_ROWSPEC, FormFactory.DEFAULT_ROWSPEC,
				FormFactory.LINE_GAP_ROWSPEC, FormFactory.DEFAULT_ROWSPEC, FormFactory.LINE_GAP_ROWSPEC,
				FormFactory.DEFAULT_ROWSPEC, FormFactory.LINE_GAP_ROWSPEC, FormFactory.DEFAULT_ROWSPEC,
				FormFactory.LINE_GAP_ROWSPEC, FormFactory.DEFAULT_ROWSPEC, FormFactory.LINE_GAP_ROWSPEC,
				FormFactory.DEFAULT_ROWSPEC, FormFactory.LINE_GAP_ROWSPEC, FormFactory.DEFAULT_ROWSPEC,
				FormFactory.LINE_GAP_ROWSPEC, FormFactory.DEFAULT_ROWSPEC, FormFactory.LINE_GAP_ROWSPEC,
				FormFactory.DEFAULT_ROWSPEC, FormFactory.LINE_GAP_ROWSPEC, FormFactory.DEFAULT_ROWSPEC,
				FormFactory.LINE_GAP_ROWSPEC, FormFactory.DEFAULT_ROWSPEC }));

		// ---- loadMeasurementLabel ----
		loadMeasurementLabel.setText("Measurement:");
		loadMeasurementLabel.setName("loadMeasurementLabel");
		add(loadMeasurementLabel, cc.xy(1, 1));

		// ---- measurementLabel ----
		measurementLabel.setName("measurementLabel");
		add(measurementLabel, cc.xy(3, 1));

		// ---- loadMeasurementButton ----
		loadMeasurementButton.setText("load");
		loadMeasurementButton.setName("loadMeasurementButton");
		add(loadMeasurementButton, cc.xy(5, 1));

		// ---- currentPositionLabel ----
		currentPositionLabel.setText("Positions:");
		currentPositionLabel.setName("currentPositionLabel");
		add(currentPositionLabel, cc.xy(1, 3));

		// ---- currentPositionSlider ----
		currentPositionSlider.setValue(0);
		currentPositionSlider.setName("currentPositionSlider");
		add(currentPositionSlider, cc.xy(3, 3));

		// ---- playPauseButton ----
		playPauseButton.setText("play");
		playPauseButton.setName("playPauseButton");
		add(playPauseButton, cc.xy(5, 3));

		// ---- loopCheckBox ----
		loopCheckBox.setText("loop?");
		loopCheckBox.setSelected(true);
		loopCheckBox.setName("loopCheckBox");
		add(loopCheckBox, cc.xywh(5, 5, 1, 1, CellConstraints.RIGHT, CellConstraints.DEFAULT));

		// ---- angleLable ----
		angleLable.setText("Angle:");
		angleLable.setName("angleLable");
		add(angleLable, cc.xy(1, 7));

		// ======== panel1 ========
		{
			panel1.setName("panel1");
			panel1.setLayout(new FlowLayout(FlowLayout.LEFT));

			// ---- angleIs0CheckBox ----
			angleIs0CheckBox.setText("0\u00b0");
			angleIs0CheckBox.setEnabled(false);
			angleIs0CheckBox.setName("angleIs0CheckBox");
			panel1.add(angleIs0CheckBox);

			// ---- angleIs90CheckBox ----
			angleIs90CheckBox.setText("90\u00b0");
			angleIs90CheckBox.setEnabled(false);
			angleIs90CheckBox.setName("angleIs90CheckBox");
			panel1.add(angleIs90CheckBox);

			// ---- angleIs180CheckBox ----
			angleIs180CheckBox.setText("180\u00b0");
			angleIs180CheckBox.setEnabled(false);
			angleIs180CheckBox.setName("angleIs180CheckBox");
			panel1.add(angleIs180CheckBox);
		}
		add(panel1, cc.xywh(3, 7, 1, 1, CellConstraints.FILL, CellConstraints.FILL));

		// ---- leftLabel ----
		leftLabel.setText("Left:");
		leftLabel.setName("leftLabel");
		add(leftLabel, cc.xy(1, 9));

		// ======== panel2 ========
		{
			panel2.setName("panel2");
			panel2.setLayout(new FlowLayout(FlowLayout.LEFT));

			// ---- leftIsLowerThanRightCheckBox ----
			leftIsLowerThanRightCheckBox.setText("< right");
			leftIsLowerThanRightCheckBox.setEnabled(false);
			leftIsLowerThanRightCheckBox.setName("leftIsLowerThanRightCheckBox");
			panel2.add(leftIsLowerThanRightCheckBox);

			// ---- leftIsLowerThanRefCheckBox ----
			leftIsLowerThanRefCheckBox.setText("< reference");
			leftIsLowerThanRefCheckBox.setEnabled(false);
			leftIsLowerThanRefCheckBox.setName("leftIsLowerThanRefCheckBox");
			panel2.add(leftIsLowerThanRefCheckBox);
		}
		add(panel2, cc.xywh(3, 9, 1, 1, CellConstraints.FILL, CellConstraints.FILL));

		// ======== panel6 ========
		{
			panel6.setName("panel6");
			panel6.setLayout(new FlowLayout(FlowLayout.LEFT));

			// ---- leftIsEqualToRightCheckBox ----
			leftIsEqualToRightCheckBox.setText("= right");
			leftIsEqualToRightCheckBox.setEnabled(false);
			leftIsEqualToRightCheckBox.setName("leftIsEqualToRightCheckBox");
			panel6.add(leftIsEqualToRightCheckBox);
		}
		add(panel6, cc.xywh(3, 11, 1, 1, CellConstraints.DEFAULT, CellConstraints.FILL));

		// ---- refLabel ----
		refLabel.setText("Reference:");
		refLabel.setName("refLabel");
		add(refLabel, cc.xy(1, 13));

		// ======== panel3 ========
		{
			panel3.setName("panel3");
			panel3.setLayout(new FlowLayout(FlowLayout.LEFT));

			// ---- refIsLowerThanLeftCheckBox ----
			refIsLowerThanLeftCheckBox.setText("< left");
			refIsLowerThanLeftCheckBox.setEnabled(false);
			refIsLowerThanLeftCheckBox.setName("refIsLowerThanLeftCheckBox");
			panel3.add(refIsLowerThanLeftCheckBox);

			// ---- refIsLowerThanRightCheckBox ----
			refIsLowerThanRightCheckBox.setText("< right");
			refIsLowerThanRightCheckBox.setEnabled(false);
			refIsLowerThanRightCheckBox.setName("refIsLowerThanRightCheckBox");
			panel3.add(refIsLowerThanRightCheckBox);
		}
		add(panel3, cc.xywh(3, 13, 1, 1, CellConstraints.DEFAULT, CellConstraints.FILL));

		// ======== panel5 ========
		{
			panel5.setName("panel5");
			panel5.setLayout(new FlowLayout(FlowLayout.LEFT));

			// ---- refIsEqualToLeftCheckBox ----
			refIsEqualToLeftCheckBox.setText("= left");
			refIsEqualToLeftCheckBox.setEnabled(false);
			refIsEqualToLeftCheckBox.setName("refIsEqualToLeftCheckBox");
			panel5.add(refIsEqualToLeftCheckBox);

			// ---- refIsEqualToRightCheckBox ----
			refIsEqualToRightCheckBox.setText("= right");
			refIsEqualToRightCheckBox.setEnabled(false);
			refIsEqualToRightCheckBox.setName("refIsEqualToRightCheckBox");
			panel5.add(refIsEqualToRightCheckBox);
		}
		add(panel5, cc.xywh(3, 15, 1, 1, CellConstraints.DEFAULT, CellConstraints.FILL));

		// ---- rightLabel ----
		rightLabel.setText("Right:");
		rightLabel.setName("rightLabel");
		add(rightLabel, cc.xy(1, 17));

		// ======== panel4 ========
		{
			panel4.setName("panel4");
			panel4.setLayout(new FlowLayout(FlowLayout.LEFT));

			// ---- rightIsLowerThanLeftCheckBox ----
			rightIsLowerThanLeftCheckBox.setText("< left");
			rightIsLowerThanLeftCheckBox.setEnabled(false);
			rightIsLowerThanLeftCheckBox.setName("rightIsLowerThanLeftCheckBox");
			panel4.add(rightIsLowerThanLeftCheckBox);

			// ---- rightIsLowerThanRefCheckBox ----
			rightIsLowerThanRefCheckBox.setText("< reference");
			rightIsLowerThanRefCheckBox.setEnabled(false);
			rightIsLowerThanRefCheckBox.setName("rightIsLowerThanRefCheckBox");
			panel4.add(rightIsLowerThanRefCheckBox);
		}
		add(panel4, cc.xywh(3, 17, 1, 1, CellConstraints.DEFAULT, CellConstraints.FILL));

		// ---- label3 ----
		label3.setText("Angle:");
		label3.setName("label3");
		add(label3, cc.xy(1, 19));

		// ---- angleToleranceTextField ----
		angleToleranceTextField.setName("angleToleranceTextField");
		add(angleToleranceTextField, cc.xywh(3, 19, 1, 1, CellConstraints.FILL, CellConstraints.DEFAULT));

		// ---- label4 ----
		label4.setText("Equal height:");
		label4.setName("label4");
		add(label4, cc.xy(1, 21));

		// ---- equalHeightToleranceTextField ----
		equalHeightToleranceTextField.setName("equalHeightToleranceTextField");
		add(equalHeightToleranceTextField, cc.xywh(3, 21, 1, 1, CellConstraints.FILL, CellConstraints.DEFAULT));

		// ---- label5 ----
		label5.setText("Lower difference:");
		label5.setName("label5");
		add(label5, cc.xy(1, 23));

		// ---- lowerDifferenceTextField ----
		lowerDifferenceTextField.setName("lowerDifferenceTextField");
		add(lowerDifferenceTextField, cc.xywh(3, 23, 1, 1, CellConstraints.FILL, CellConstraints.DEFAULT));

		// ---- label6 ----
		label6.setText("zOffset:");
		label6.setName("label6");
		add(label6, cc.xy(1, 25));

		// ---- zOffsetTextField ----
		zOffsetTextField.setName("zOffsetTextField");
		add(zOffsetTextField, cc.xy(3, 25));

		// ---- label7 ----
		label7.setText("GeReco time:");
		label7.setName("label7");
		add(label7, cc.xy(1, 27));

		// ---- geRecoTimeTextField ----
		geRecoTimeTextField.setName("geRecoTimeTextField");
		add(geRecoTimeTextField, cc.xy(3, 27));

		// ---- label8 ----
		label8.setText("GeReco treshold:");
		label8.setName("label8");
		add(label8, cc.xy(1, 29));

		// ---- geRecoTresholdTextField ----
		geRecoTresholdTextField.setName("geRecoTresholdTextField");
		add(geRecoTresholdTextField, cc.xy(3, 29));
		// //GEN-END:initComponents
	}

	// JFormDesigner - Variables declaration - DO NOT MODIFY
	// //GEN-BEGIN:variables
	// Generated using JFormDesigner Open Source Project license - unknown
	private JLabel measurementLabel;
	private JButton loadMeasurementButton;
	private JLabel currentPositionLabel;
	private JSlider currentPositionSlider;
	private JButton playPauseButton;
	private JCheckBox loopCheckBox;
	private JCheckBox angleIs0CheckBox;
	private JCheckBox angleIs90CheckBox;
	private JCheckBox angleIs180CheckBox;
	private JCheckBox leftIsLowerThanRightCheckBox;
	private JCheckBox leftIsLowerThanRefCheckBox;
	private JPanel panel6;
	private JCheckBox leftIsEqualToRightCheckBox;
	private JCheckBox refIsLowerThanLeftCheckBox;
	private JCheckBox refIsLowerThanRightCheckBox;
	private JCheckBox refIsEqualToLeftCheckBox;
	private JCheckBox refIsEqualToRightCheckBox;
	private JCheckBox rightIsLowerThanLeftCheckBox;
	private JCheckBox rightIsLowerThanRefCheckBox;
	private JLabel label3;
	private JTextField angleToleranceTextField;
	private JLabel label4;
	private JTextField equalHeightToleranceTextField;
	private JLabel label5;
	private JTextField lowerDifferenceTextField;
	private JLabel label6;
	private JTextField zOffsetTextField;
	private JLabel label7;
	private JTextField geRecoTimeTextField;
	private JLabel label8;
	private JTextField geRecoTresholdTextField;
	// JFormDesigner - End of variables declaration //GEN-END:variables

	private TagAssignmentPanel tagAssignmentPanel;

	@Override
	public void tagPositionChanged(TagPosition tagPosition, Position newPosition)
	{
		if (fileServerSimulator.isPlaying())
		{
			int currentPos = fileServerSimulator.getCurrentPosition();
			currentPositionSlider.setValue(currentPos);
		}
	}

	public void setTagAssignmentPanel(TagAssignmentPanel tagAssignmentPanel)
	{
		this.tagAssignmentPanel = tagAssignmentPanel;
	}

	public void setGestureCharacteristics(GestureCharacteristics gc)
	{
		angleIs0CheckBox.setSelected(gc.angleIs0());
		angleIs90CheckBox.setSelected(gc.angleIs90());
		angleIs180CheckBox.setSelected(gc.angleIs180());

		leftIsLowerThanRightCheckBox.setSelected(gc.leftIsLowerThanRight());
		leftIsLowerThanRefCheckBox.setSelected(gc.leftIsLowerThanRef());
		leftIsEqualToRightCheckBox.setSelected(gc.leftHasEqualHeightToRight());

		refIsEqualToLeftCheckBox.setSelected(gc.refHasEqualHeightToLeft());
		refIsEqualToRightCheckBox.setSelected(gc.refHasEqualHeightToRight());
		refIsLowerThanLeftCheckBox.setSelected(gc.refIsLowerThanLeft());
		refIsLowerThanRightCheckBox.setSelected(gc.refIsLowerThanRight());

		rightIsLowerThanLeftCheckBox.setSelected(gc.rightIsLowerThanLeft());
		rightIsLowerThanRefCheckBox.setSelected(gc.rightIsLowerThanRef());
	}
}
